package com.zf.yichat.service.impl;

import com.github.pagehelper.PageHelper;
import com.zf.yichat.IntegralInfoDto;
import com.zf.yichat.dto.IntegralDetailListDto;
import com.zf.yichat.mapper.UserIntegralDetailMapper;
import com.zf.yichat.mapper.UserMapper;
import com.zf.yichat.model.SysDict;
import com.zf.yichat.model.SysDictData;
import com.zf.yichat.model.User;
import com.zf.yichat.model.UserIntegralDetail;
import com.zf.yichat.service.SysDictService;
import com.zf.yichat.service.UserIntegralService;
import com.zf.yichat.service.UserService;
import com.zf.yichat.utils.YiChatMsgCode;
import com.zf.yichat.utils.common.DateUtils;
import com.zf.yichat.utils.common.DtoChangeUtils;
import com.zf.yichat.utils.response.FsPage;
import com.zf.yichat.utils.response.FsResponse;
import com.zf.yichat.utils.response.FsResponseGen;
import com.zf.yichat.vo.DictKey;
import com.zf.yichat.vo.IntegralType;
import org.apache.commons.lang3.math.NumberUtils;
import org.hibernate.validator.internal.util.Contracts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 一句话描述功能
 *
 * @author fengsong
 * @date create in 14:10 2020/3/25 2020
 */
@Service
public class UserIntegralServiceImpl implements UserIntegralService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private UserIntegralDetailMapper userIntegralDetailMapper;

    @Autowired
    private UserService userService;

    @Override
    public FsResponse getIntegral(IntegralType type, Long userId, String referId) {


        switch (type) {
            //签到 每天只能签到一次
            case SIGN:
                UserIntegralDetail detail = selectLastByType(type, userId);
                if (Objects.nonNull(detail) && detail.getCtime().getTime() > DateUtils.parse(DateUtils.formatCurrentDate("yyyy-MM-dd") + " 00:00:00").getTime()) {
                    return FsResponseGen.success(YiChatMsgCode.INTEGRAL_SIGN_REPEAT);
                }
                //查询配置的签到获取积分
                Integer preSign = NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_sign).getValue());
                updateDetail(IntegralType.SIGN, null, preSign, userId);
                break;
            case INVITE:
                //查询邀请人获取积分
                Integer invite = NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_invite).getValue());
                //被邀请人获取积分 referID 此时为被邀请人
                updateDetail(IntegralType.INVITE, referId, invite, userId);
                break;

            default:
        }

        if (type.getVal() == IntegralType.SHARE_QQ_AROUND.getVal()
                || type.getVal() == IntegralType.SHARE_QQ_FREIND.getVal()
                || type.getVal() == IntegralType.SHARE_WX_AROUND.getVal()
                || type.getVal() == IntegralType.SHARE_WX_FRIENDS.getVal()) {

            Integer share = NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_share).getValue());
            Integer limitShare = NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_share_limit).getValue());

            //如果当前分享已超过次数 则不添加
            Integer count = countDayByType(type, userId);
            if (count < limitShare) {
                updateDetail(type, referId, share, userId);
            }
        }

        return info(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDetail(IntegralType type, String referId, Integer score, Long userId) {

        //增加记录
        UserIntegralDetail detail = new UserIntegralDetail();
        detail.setIntegral(score);
        detail.setReferType(type.getVal());
        detail.setMemo(type.getDesc());
        detail.setUserId(userId);
        detail.setReferId(referId);

        userIntegralDetailMapper.insertSelective(detail);

        //增加积分值
        userMapper.addIntegral(score, userId);

    }

    @Override
    public UserIntegralDetail selectLastByType(IntegralType type, Long userId) {
        Example example = new Example(UserIntegralDetail.class);
        example.createCriteria().andEqualTo("userId", userId).andEqualTo("referType", type.getVal());
        example.setOrderByClause(" id desc limit 1");
        return userIntegralDetailMapper.selectOneByExample(example);
    }

    @Override
    public int countDayByType(IntegralType type, Long userId) {
        Example example = new Example(UserIntegralDetail.class);
        example.createCriteria().andEqualTo("userId", userId)
                .andEqualTo("referType", type.getVal())
                .andGreaterThanOrEqualTo("ctime", DateUtils.formatCurrentDate("yyyy-MM-dd") + DateUtils.TIME_START_SUFFIX)
                .andLessThan("ctime", DateUtils.formatCurrentDate("yyyy-MM-dd") + DateUtils.TIME_END_SUFFIX);

        return userIntegralDetailMapper.selectCountByExample(example);
    }

    @Override
    public FsResponse detailInfo(FsPage init, Long userId) {
        Example example = new Example(UserIntegralDetail.class);
        example.createCriteria().andEqualTo("userId", userId);
        example.setOrderByClause(" id desc");
        PageHelper.startPage(init.getPageNo(), init.getPageSize());
        return DtoChangeUtils.getPageList(userIntegralDetailMapper.selectByExample(example), v -> {
            IntegralDetailListDto dto = new IntegralDetailListDto();
            dto.setMemo(v.getMemo() + " : " + v.getIntegral() + "积分");
            dto.setIntegral(v.getIntegral());
            dto.setTimeDesc(DateUtils.formatDate(v.getCtime(), "yyyy-MM-dd HH:mm:ss"));
            return dto;
        });
    }

    @Override
    public FsResponse info(Long userId) {

        IntegralInfoDto dto = new IntegralInfoDto();
        dto.setIntegral(userService.selectById(userId).getIntegral());

        //根据当前积分 划分登记
        dto.setLevel(selectLevel(dto.getIntegral()).getName());

        Example example = new Example(UserIntegralDetail.class);
        example.createCriteria().andEqualTo("userId", userId);
        example.setOrderByClause(" id desc limit 1");

        dto.setLastMemo(Optional.ofNullable(userIntegralDetailMapper.selectOneByExample(example)).map(v -> v.getMemo() + "获取" + v.getIntegral() + "积分").orElse(""));

        dto.setRulecontent(sysDictService.selectOne(DictKey.integral_content).getMemo());
        dto.setTitle(sysDictService.selectOne(DictKey.share_title).getMemo());
//        dto.setShareIntegral(Optional.ofNullable(countShare(userId)).orElse(0));
        dto.setShareIntegral(NumberUtils.toInt(sysDictService.selectOne(DictKey.integral_share).getValue()));
        dto.setShareDes(sysDictService.selectOne(DictKey.share_content).getMemo());
        dto.setWebUrl(sysDictService.selectOne(DictKey.share_url).getMemo());

        return FsResponseGen.successData(dto);
    }

    @Override
    public SysDictData selectLevel(Integer integral) {

        List<SysDictData> list = sysDictService.selectData(DictKey.integral_level);


        for (SysDictData data : list) {
            if (integral < Long.parseLong(data.getValue())) {
                return data;
            }

        }

        return null;
    }

    @Override
    public Integer countShare(Long userId) {
        return userIntegralDetailMapper.sumShare(userId);
    }

    @Override
    public void giveIntegralForType(Long userId, String type) {

        // 注册类型
        if (User.REGISTER_TYPE.equals(type)) {
            Example exampleRegister = new Example(UserIntegralDetail.class);
            Example.Criteria criteriaRegister = exampleRegister.createCriteria();
            criteriaRegister.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.REGISTER_CONSUME.getVal());
            List<UserIntegralDetail> registerList = userIntegralDetailMapper.selectByExample(exampleRegister);
            Contracts.assertTrue(null == registerList || registerList.size() == 0, "注册赠送积分已领取，请勿重复！");

            SysDict sysDict = sysDictService.selectOne(DictKey.user_register_give_integral);
            Integer integral = 0;
            if (null == sysDict) {
                integral = 0;
            }else {
                integral = Integer.valueOf(sysDict.getValue());
            }

            updateDetail(IntegralType.REGISTER_CONSUME, userId + ":" + User.REGISTER_TYPE, integral, userId);

        }
        // 实名认证
        else if (User.REAL_NAME_TYPE.equals(type)) {
            Example exampleRealName = new Example(UserIntegralDetail.class);
            Example.Criteria criteriaRealName = exampleRealName.createCriteria();
            criteriaRealName.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.REAL_NAME_CONSUME.getVal());
            List<UserIntegralDetail> realNameList = userIntegralDetailMapper.selectByExample(exampleRealName);
            Contracts.assertTrue(null == realNameList || realNameList.size() == 0, "实名认证赠送积分已领取，请勿重复！");

            SysDict sysDict = sysDictService.selectOne(DictKey.user_real_name_give_integral);
            Integer integral = 0;
            if (null == sysDict) {
                integral = 0;
            }
            else {
                integral = Integer.valueOf(sysDict.getValue());
            }


            updateDetail(IntegralType.REAL_NAME_CONSUME, userId  + ":" + User.REAL_NAME_TYPE, integral, userId);

        }
        else if (User.BIND_CARD_TYPE.equals(type)){
            Example exampleCard = new Example(UserIntegralDetail.class);
            Example.Criteria criteriaCard = exampleCard.createCriteria();
            criteriaCard.andEqualTo("userId", userId).andEqualTo("referType", IntegralType.BIND_CARD_CONSUME.getVal());
            List<UserIntegralDetail> cardList = userIntegralDetailMapper.selectByExample(exampleCard);
            Contracts.assertTrue(null == cardList || cardList.size() == 0, "绑卡赠送积分已领取，请勿重复！");

            // 绑卡
            SysDict sysDict = sysDictService.selectOne(DictKey.user_bind_card_give_integral);

            Integer integral = 0;
            if (null == sysDict) {
                integral = 0;
            }
            else {
                integral = Integer.valueOf(sysDict.getValue());
            }

            updateDetail(IntegralType.BIND_CARD_CONSUME, userId  + ":" + User.BIND_CARD_TYPE, integral, userId);
        }
        else {
            Contracts.assertTrue(true, "赠送积分类型错误！");
        }
    }
}
